package com.culture.bootdemo.designPattern设计模式.single单例;

/**
 * @Author: wenjl
 * @Date: 2021/7/23 15:11
 * @Description:
 */
public class SingleDemo {
    /**
     * 双重校验锁形式（DCL）：double-checked-locking
     * 懒汉模式为线程不安全的，在此基础上加上并发控制，保证线程安全，对外存一个对象
     * 实现：
     * 1.  构造器私有化：避免外部new 构造器
     * 2.  提供私有静态属性：存储对象地址
     * 3.  提供公共静态方法：获取属性
     **/


    // volatile 关键字 防止发生指令重排序
    private static volatile SingleDemo instance;

    private SingleDemo() {
    }

    public static SingleDemo getInstance() {
        //这个判断是为了提高性能，以免每次都要进同步代码块
        if (null != instance) {
            return instance;
        }
        //若不加volatile，则线程开辟空间了，不为null了，但是还没创建完，此时有一个线程进来，直接上面判断不为空，返回的对象是不完整的对象，会抛异常。
        synchronized (SingleDemo.class) {
            //进行第二次非空判断，是因为synchronized上面已经进来多个线程了。
            //例：有3个线程同时进来，判断=null,则排队进入同步代码块里，第一个进来实例化完，第二个再进来时候，对象已经有了，则不需要进行new操作了，否则再进行一次，最后便生成多个实例了。
            if (null == instance) {
                /* new一个对象分为三步：
                 * 1. 开辟内存空间
                 * 2. 初始化对象（调用构造器方法）
                 * 3. 将对象引用指向分配的内存空间
                 */
                //指令重排出问题是在 2，3步互换
                instance = new SingleDemo();
            }
        }
        return instance;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " : " + SingleDemo.getInstance().hashCode());
            }).start();
        }
    }


}
